<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Life cycle callbacks test</title>

</head>
<style>
    custom-square {
        margin: 20px;
    }
</style>

<body>
    <!-- https://github.com/mdn/web-components-examples/blob/main/life-cycle-callbacks/main.js -->
    <h1>Life cycle callbacks test</h1>

    <div>
        <button class="add">Add custom-square to DOM</button>
        <button class="update">Update attributes</button>
        <button class="remove">Remove custom-square from DOM</button>
    </div>
    <script>
        // Create a class for the element
        class Square extends HTMLElement {
            // Specify observed attributes so that
            // attributeChangedCallback will work
            static get observedAttributes() {
                return ['c', 'l'];
            }

            constructor() {
                // Always call super first in constructor
                super();

                const shadow = this.attachShadow({ mode: 'open' });

                const div = document.createElement('div');
                const style = document.createElement('style');
                shadow.appendChild(style);
                shadow.appendChild(div);
            }

            connectedCallback() {
                console.log('Custom square element added to page.');
                updateStyle(this);
            }

            disconnectedCallback() {
                console.log('Custom square element removed from page.');
            }

            adoptedCallback() {
                console.log('Custom square element moved to new page.');
            }

            attributeChangedCallback(name, oldValue, newValue) {
                console.log('Custom square element attributes changed.');
                updateStyle(this);
            }
        }

        customElements.define('custom-square', Square);

        function updateStyle(elem) {
            const shadow = elem.shadowRoot;
            shadow.querySelector('style').textContent = `
    div {
      width: ${elem.getAttribute('l')}px;
      height: ${elem.getAttribute('l')}px;
      background-color: ${elem.getAttribute('c')};
    }
  `;
        }

        const add = document.querySelector('.add');
        const update = document.querySelector('.update');
        const remove = document.querySelector('.remove');
        let square;

        update.disabled = true;
        remove.disabled = true;

        function random(min, max) {
            return Math.floor(Math.random() * (max - min + 1) + min);
        }

        add.onclick = function () {
            // Create a custom square element
            square = document.createElement('custom-square');
            square.setAttribute('l', '100');
            square.setAttribute('c', 'red');
            document.body.appendChild(square);

            update.disabled = false;
            remove.disabled = false;
            add.disabled = true;
        };

        update.onclick = function () {
            // Randomly update square's attributes
            square.setAttribute('l', random(50, 200));
            square.setAttribute('c', `rgb(${random(0, 255)}, ${random(0, 255)}, ${random(0, 255)})`);
        };

        remove.onclick = function () {
            // Remove the square
            document.body.removeChild(square);

            update.disabled = true;
            remove.disabled = true;
            add.disabled = false;
        };
      // 这里定义了可以在 DOM 树上直接使用的真实节点
    </script>
</body>

</html>